// BreezeShl.cpp : Implementation of CBreezeShl
#include "stdafx.h"
#include "BreezeCopy.h"
#include "BreezeShl.h"

/////////////////////////////////////////////////////////////////////////////
// CBreezeShl constructor

CBreezeShl::CBreezeShl()
{
confData tmpStruct;
int strPos, strPos2, strPos3;
std::string tStr, line, tline;
std::ifstream confFile;
CRegKey reg;
LONG lRet;
char szValue[MAX_PATH];
DWORD dwValue = MAX_PATH;

	lRet = reg.Open(HKEY_LOCAL_MACHINE, _T("Software\\BreezeWorkz\\BreezeSCP"), KEY_QUERY_VALUE);

	if ( lRet == 0 )
	{
		lRet = reg.QueryValue(szValue, _T("ConfigPath"), &dwValue);
	}

	reg.Close();

	if ( lRet == 0 )
	{
		confFile.open(szValue);

		if ( !confFile.fail() )
		{
			while ( !confFile.eof() )
			{
				std::getline(confFile, line);

				if ( !line.length() )
					continue;

				strPos = line.find('\t');

				if ( strPos != -1 )
				{
					strPos2 = line.find('\t', strPos+1);
					
					if ( strPos2 != -1 )
					{
						strPos3 = line.find('\t', strPos2+1);

						if ( strPos3 != -1 )
						{
							tline = line.substr(0,strPos);
							tmpStruct.name = strdup(tline.c_str());

							tline = line.substr(strPos+1, ((strPos2 - strPos) - 1));
							tmpStruct.token = strdup(tline.c_str());

							tline = line.substr(strPos2+1, ((strPos3 - strPos2) - 1));
							tmpStruct.authtype = atoi(tline.c_str());

							tline = line.substr(strPos3+1);
							tmpStruct.auth = strdup(tline.c_str());

							m_lsConfig.push_back(tmpStruct);
						}
					}
				}
			}
		}
	}

	confFile.close();
/*
    //create an entry in our struct_list
	tmpStruct.name = "mrm@mrmittens.com:/tmp/";
	tmpStruct.token = "yoyo_1111";
	m_lsConfig.push_back(tmpStruct); 
*/
	tmpStruct.name = "configure...";
	tmpStruct.token = "configure";
	m_lsConfig.push_back(tmpStruct);

	// load our icon
    m_hShellBmp = LoadBitmap(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDB_BREEZEBMP));
}

/////////////////////////////////////////////////////////////////////////////
// CBreezeShl IShellExtInit methods


//////////////////////////////////////////////////////////////////////////
//
// Function:    Initialize()
//
// Description:
//  Reads in the list of selected files/folders and stores them for later use.
//
//////////////////////////////////////////////////////////////////////////

HRESULT CBreezeShl::Initialize( LPCITEMIDLIST pidlFolder,
                                LPDATAOBJECT  pDataObj,
                                HKEY          hProgID )
{
TCHAR     szFile    [MAX_PATH];
UINT      uNumFiles, uFile;
HDROP     hdrop;
FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stg = { TYMED_HGLOBAL };

    // read the list of items from the data object. they're stored in HDROP form
    // so just get the HDROP handle and then use the drag 'n' drop APIs on it.

    if ( FAILED(pDataObj->GetData(&etc, &stg)) )
        return E_INVALIDARG;

    // get an HDROP handle
    hdrop = (HDROP) GlobalLock(stg.hGlobal);

    if ( NULL == hdrop )
    {
        ReleaseStgMedium(&stg);
        return E_INVALIDARG;
    }

    // determine how many files are involved in this operation
    uNumFiles = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);

    for ( uFile = 0; uFile < uNumFiles; uFile++ )
    {
        // get the next filename
        if ( DragQueryFile(hdrop, uFile, szFile, MAX_PATH) == 0 )
		{
            continue;
		}

		m_lsFiles.push_back(szFile);

    }

    // release resources
    GlobalUnlock(stg.hGlobal);
    ReleaseStgMedium(&stg);

	// if there are more than 0 files in the list return S_OK, otherwise
	// return E_INVALIDARG so we dont get called again for this right-click event.

    return ( m_lsFiles.size() > 0 ) ? S_OK : E_INVALIDARG;
}


/////////////////////////////////////////////////////////////////////////////
// CBreezeShl IContextMenu methods

//////////////////////////////////////////////////////////////////////////
//
// Function:    QueryContextMenu()
//
// Description:
//  Adds our items to the supplied menu.
//
//////////////////////////////////////////////////////////////////////////

HRESULT CBreezeShl::QueryContextMenu( HMENU hmenu,       UINT uMenuIndex, 
                                      UINT  uidFirstCmd, UINT uidLastCmd,
                                      UINT  uFlags )
{
    // If the flags include CMF_DEFAULTONLY then we shouldn't do anything.

    if ( uFlags & CMF_DEFAULTONLY )
    {
        return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
    }

HMENU hSubmenu = CreatePopupMenu();
UINT uID = uidFirstCmd;
UINT uOrder = 0;
struct_list::iterator it;
char *dispName;

	//create submenus

	for ( it = m_lsConfig.begin(); it != m_lsConfig.end(); it++ )
	{
		dispName = (char *) it->name;
		if ( (strcmp(dispName, "configure...") == 0) && (uOrder >= 1))
		{
			InsertMenu(hSubmenu, uOrder++, MF_BYPOSITION |MF_SEPARATOR, uID++, _T("&sep"));
		}
		it->order = uOrder;

		InsertMenu(hSubmenu, uOrder++, MF_BYPOSITION, uID++, dispName);
	}

/*	InsertMenu(hSubmenu, uOrder++, MF_BYPOSITION | MF_SEPARATOR, uID++, _T("&sep"));
	InsertMenu(hSubmenu, uOrder++, MF_BYPOSITION, uID++, _T("configure"));

    InsertMenu(hSubmenu, 1, MF_BYPOSITION, uID++, _T("&blam"));
    InsertMenu(hSubmenu, 2, MF_BYPOSITION, uID++, _T("&blaow"));
	InsertMenu(hSubmenu, 3, MF_BYPOSITION | MF_SEPARATOR, uID++, _T("&sep"));
	InsertMenu(hSubmenu, 4, MF_BYPOSITION, uID++, _T("configure"));              */

    // insert them into the main menu
MENUITEMINFO mii = { sizeof(MENUITEMINFO) };

	mii.fMask = MIIM_SUBMENU | MIIM_STRING | MIIM_ID;
    mii.wID = uID++;
    mii.hSubMenu = hSubmenu;
    mii.dwTypeData = _T("BreezeSCP");
	
    InsertMenuItem(hmenu, uMenuIndex, TRUE, &mii);

    // set the bitmap for the main menu
    if ( NULL != m_hShellBmp )
    {
        SetMenuItemBitmaps(hmenu, uMenuIndex, MF_BYPOSITION, m_hShellBmp, NULL);
    }

    // The return value tells the shell how many top-level items we added.

    return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, uID - uidFirstCmd);
}


//////////////////////////////////////////////////////////////////////////
//
// Function:    GetCommandString()
//
// Description:
//  Sets the flyby help string for the Explorer status bar.
//
//////////////////////////////////////////////////////////////////////////

HRESULT CBreezeShl::GetCommandString ( UINT  uCmdID,     UINT uFlags, 
                                       UINT* puReserved, LPSTR szName,
                                       UINT  cchMax )
{
LPCTSTR szPrompt = _T("SCP file(s).");

    USES_CONVERSION;

    if ( uFlags & GCS_HELPTEXT )
    {
		/*
		if ( uCmdID =! 0 )
			return E_INVALIDARG;
		*/

        // copy the help text into the supplied buffer. if the shell wants
        // a unicode string, we need to cast szName to an LPCWSTR.

        if ( uFlags & GCS_UNICODE )
        {
            lstrcpynW((LPWSTR) szName, T2CW(szPrompt), cchMax);
        }
        else
        {
            lstrcpynA(szName, T2CA(szPrompt), cchMax);
        }
    }
    else if ( uFlags & GCS_VERB )
    {
        // Copy the verb name into the supplied buffer.  If the shell wants
        // a Unicode string, we need to case szName to an LPCWSTR.

        if ( uFlags & GCS_UNICODE )
        {
            lstrcpynW((LPWSTR) szName, L"BreezeSvr", cchMax);
        }
        else
        {
            lstrcpynA(szName, "BreezeSvr", cchMax);
        }
    }

    return S_OK;
}


//////////////////////////////////////////////////////////////////////////
//
// Function:    InvokeCommand()
//
// Description:
//  Carries out the selected command.
//
//////////////////////////////////////////////////////////////////////////

HRESULT CBreezeShl::InvokeCommand( LPCMINVOKECOMMANDINFO pInfo )
{
	// if lpVerb points to a string, ignore this function call and bail out
    if ( 0 != HIWORD(pInfo->lpVerb) )
		return E_INVALIDARG;

	if ( ( LOWORD(pInfo->lpVerb) > 30 ) || ( LOWORD(pInfo->lpVerb) < 0) )
		return E_INVALIDARG;

string_list::const_iterator it;
struct_list::const_iterator it2;
std::string tCmd = "";
unsigned short tCalled;
CRegKey reg;
LONG lRet;
char szValue[MAX_PATH];
DWORD dwValue = MAX_PATH;
	
	lRet = reg.Open(HKEY_LOCAL_MACHINE, _T("Software\\BreezeWorkz\\BreezeSCP"), KEY_QUERY_VALUE);

	if ( lRet == 0 )
	{
		lRet = reg.QueryValue(szValue, _T("PuttySCPPath"), &dwValue);
	}

	reg.Close();

	if ( lRet != 0 )
	{
		MessageBox(pInfo->hwnd, _T("You need to configure your putty path."), _T("BreezeSCP"), MB_ICONINFORMATION);
		return E_INVALIDARG;
	}
	else
	{
		tCmd += "cmd.exe /C \"\"";
		tCmd += szValue;
		tCmd += "\" -r ";
	}

	tCalled = (int) LOWORD(pInfo->lpVerb);

	for ( it2 = m_lsConfig.begin(); it2 != m_lsConfig.end(); it2++ )
	{
		if ( it2->order == tCalled )
		{
			break;
		}
	}

	if ( strcmp(it2->token,"configure") == 0 )
	{
		lRet = reg.Open(HKEY_LOCAL_MACHINE, _T("Software\\BreezeWorkz\\BreezeSCP"), KEY_QUERY_VALUE);

		if ( lRet == 0 )
		{
			dwValue = MAX_PATH;
			lRet = reg.QueryValue(szValue, _T("SetupPath"), &dwValue);
		}

		reg.Close();

		if ( lRet == 0 )
		{
			//stat the binary here
			WinExec(szValue, SW_SHOWNORMAL);
			//MessageBox(pInfo->hwnd, szValue, _T("Executing"), MB_ICONINFORMATION);
		}
		else
		{		
			MessageBox(pInfo->hwnd, _T("ERROR(A1): please reinstall."), _T("BreezeSCP Error!"), MB_ICONERROR);
		}

		m_lsConfig.clear();
		return S_OK;
	}

	if ( it2->authtype == 1 )
	{
		tCmd += "-pw \"";
		tCmd += it2->auth;
		tCmd += "\" ";
	}
	else if ( it2->authtype == 2 )
	{
		tCmd += "-i \"";
		tCmd += it2->auth;
		tCmd += "\" ";
	}

	for ( it = m_lsFiles.begin(); it != m_lsFiles.end(); it++ )
	{	
		tCmd += "\"";
		tCmd += it->c_str();
		tCmd += "\" ";
	}

	tCmd += it2->token;
	tCmd += " && pause || pause\"";

	//MessageBox(pInfo->hwnd, tCmd.c_str(), _T("Testing"), MB_ICONINFORMATION);
	WinExec(tCmd.c_str(), SW_SHOWNORMAL);

	m_lsConfig.clear();

    return S_OK;
}
	